!> author: 左志华
!> date: 2022/05/12
!>
!> GSL 库的快速傅里叶变换
module gsl_fft_m

    use, intrinsic :: iso_c_binding

    interface
        function gsl_fft_complex_radix2_forward(data, stride, n) bind(c)
            import :: c_size_t, c_ptr, c_int
            integer(c_size_t), value :: stride, n
            type(c_ptr), value :: data
            integer(c_int) :: gsl_fft_complex_radix2_forward
        end function gsl_fft_complex_radix2_forward
        function gsl_fft_complex_radix2_transform(data, stride, n, sign) bind(c)
            import :: c_size_t, c_ptr, c_int
            integer(c_size_t), value :: stride, n
            type(c_ptr), value :: data
            integer(c_int), value :: sign
            integer(c_int) :: gsl_fft_complex_radix2_transform
        end function gsl_fft_complex_radix2_transform
        function gsl_fft_complex_radix2_backward(data, stride, n) bind(c)
            import :: c_size_t, c_ptr, c_int
            integer(c_size_t), value :: stride, n
            type(c_ptr), value :: data
            integer(c_int) :: gsl_fft_complex_radix2_backward
        end function gsl_fft_complex_radix2_backward
        function gsl_fft_complex_radix2_inverse(data, stride, n) bind(c)
            import :: c_size_t, c_ptr, c_int
            integer(c_size_t), value :: stride, n
            type(c_ptr), value :: data
            integer(c_int) :: gsl_fft_complex_radix2_inverse
        end function gsl_fft_complex_radix2_inverse
        function gsl_fft_complex_radix2_dif_forward(data, stride, n) bind(c)
            import :: c_size_t, c_ptr, c_int
            integer(c_size_t), value :: stride, n
            type(c_ptr), value :: data
            integer(c_int) :: gsl_fft_complex_radix2_dif_forward
        end function gsl_fft_complex_radix2_dif_forward
        function gsl_fft_complex_radix2_dif_transform(data, stride, n, sign) bind(c)
            import :: c_size_t, c_ptr, c_int
            integer(c_size_t), value :: stride, n
            type(c_ptr), value :: data
            integer(c_int), value :: sign
            integer(c_int) :: gsl_fft_complex_radix2_dif_transform
        end function gsl_fft_complex_radix2_dif_transform
        function gsl_fft_complex_radix2_dif_backward(data, stride, n) bind(c)
            import :: c_size_t, c_ptr, c_int
            integer(c_size_t), value :: stride, n
            type(c_ptr), value :: data
            integer(c_int) :: gsl_fft_complex_radix2_dif_backward
        end function gsl_fft_complex_radix2_dif_backward
        function gsl_fft_complex_radix2_dif_inverse(data, stride, n) bind(c)
            import :: c_size_t, c_ptr, c_int
            integer(c_size_t), value :: stride, n
            type(c_ptr), value :: data
            integer(c_int) :: gsl_fft_complex_radix2_dif_inverse
        end function gsl_fft_complex_radix2_dif_inverse
!
        function gsl_fft_complex_wavetable_alloc(n) bind(c)
            import :: c_size_t, c_ptr
            integer(c_size_t), value :: n
            type(c_ptr) :: gsl_fft_complex_wavetable_alloc
        end function gsl_fft_complex_wavetable_alloc
        subroutine gsl_fft_complex_wavetable_free(w) bind(c)
            import :: c_ptr
            type(c_ptr), value :: w
        end subroutine gsl_fft_complex_wavetable_free
        function gsl_fft_complex_workspace_alloc(n) bind(c)
            import :: c_size_t, c_ptr
            integer(c_size_t), value :: n
            type(c_ptr) :: gsl_fft_complex_workspace_alloc
        end function gsl_fft_complex_workspace_alloc
        subroutine gsl_fft_complex_workspace_free(w) bind(c)
            import :: c_ptr
            type(c_ptr), value :: w
        end subroutine gsl_fft_complex_workspace_free
        function gsl_fft_complex_forward(data, stride, n, wavetable, work) bind(c)
            import :: c_size_t, c_ptr, c_int
            integer(c_size_t), value :: stride, n
            type(c_ptr), value :: data, wavetable, work
            integer(c_int) :: gsl_fft_complex_forward
        end function gsl_fft_complex_forward
        function gsl_fft_complex_transform(data, stride, n, wavetable, work, sign) &
            bind(c)
            import :: c_size_t, c_ptr, c_int
            integer(c_size_t), value :: stride, n
            type(c_ptr), value :: data, wavetable, work
            integer(c_int), value :: sign
            integer(c_int) :: gsl_fft_complex_transform
        end function gsl_fft_complex_transform
        function gsl_fft_complex_backward(data, stride, n, wavetable, work) bind(c)
            import :: c_size_t, c_ptr, c_int
            integer(c_size_t), value :: stride, n
            type(c_ptr), value :: data, wavetable, work
            integer(c_int) :: gsl_fft_complex_backward
        end function gsl_fft_complex_backward
        function gsl_fft_complex_inverse(data, stride, n, wavetable, work) bind(c)
            import :: c_size_t, c_ptr, c_int
            integer(c_size_t), value :: stride, n
            type(c_ptr), value :: data, wavetable, work
            integer(c_int) :: gsl_fft_complex_inverse
        end function gsl_fft_complex_inverse
        function gsl_fft_real_radix2_transform(data, stride, n) bind(c)
            import :: c_size_t, c_ptr, c_int
            integer(c_size_t), value :: stride, n
            type(c_ptr), value :: data
            integer(c_int) :: gsl_fft_real_radix2_transform
        end function gsl_fft_real_radix2_transform
        function gsl_fft_halfcomplex_radix2_inverse(data, stride, n) bind(c)
            import :: c_size_t, c_ptr, c_int
            integer(c_size_t), value :: stride, n
            type(c_ptr), value :: data
            integer(c_int) :: gsl_fft_halfcomplex_radix2_inverse
        end function gsl_fft_halfcomplex_radix2_inverse
        function gsl_fft_halfcomplex_radix2_backward(data, stride, n) bind(c)
            import :: c_size_t, c_ptr, c_int
            integer(c_size_t), value :: stride, n
            type(c_ptr), value :: data
            integer(c_int) :: gsl_fft_halfcomplex_radix2_backward
        end function gsl_fft_halfcomplex_radix2_backward
        function gsl_fft_real_wavetable_alloc(n) bind(c)
            import :: c_size_t, c_ptr
            integer(c_size_t), value :: n
            type(c_ptr) :: gsl_fft_real_wavetable_alloc
        end function gsl_fft_real_wavetable_alloc
        subroutine gsl_fft_real_wavetable_free(w) bind(c)
            import :: c_ptr
            type(c_ptr), value :: w
        end subroutine gsl_fft_real_wavetable_free
        function gsl_fft_halfcomplex_wavetable_alloc(n) bind(c)
            import :: c_size_t, c_ptr
            integer(c_size_t), value :: n
            type(c_ptr) :: gsl_fft_halfcomplex_wavetable_alloc
        end function gsl_fft_halfcomplex_wavetable_alloc
        subroutine gsl_fft_halfcomplex_wavetable_free(w) bind(c)
            import :: c_ptr
            type(c_ptr), value :: w
        end subroutine gsl_fft_halfcomplex_wavetable_free
        function gsl_fft_real_workspace_alloc(n) bind(c)
            import :: c_size_t, c_ptr
            integer(c_size_t), value :: n
            type(c_ptr) :: gsl_fft_real_workspace_alloc
        end function gsl_fft_real_workspace_alloc
        subroutine gsl_fft_real_workspace_free(w) bind(c)
            import :: c_ptr
            type(c_ptr), value :: w
        end subroutine gsl_fft_real_workspace_free
        function gsl_fft_real_transform(data, stride, n, wavetable, work) &
            bind(c)
            import :: c_size_t, c_ptr, c_int
            integer(c_size_t), value :: stride, n
            type(c_ptr), value :: data, wavetable, work
            integer(c_int) :: gsl_fft_real_transform
        end function gsl_fft_real_transform
        function gsl_fft_halfcomplex_transform(data, stride, n, wavetable, work) &
            bind(c)
            import :: c_size_t, c_ptr, c_int
            integer(c_size_t), value :: stride, n
            type(c_ptr), value :: data, wavetable, work
            integer(c_int) :: gsl_fft_halfcomplex_transform
        end function gsl_fft_halfcomplex_transform
        function gsl_fft_real_unpack(real_coefficient, complex_coefficient, &
                                     stride, n) bind(c)
            import :: c_size_t, c_ptr, c_int
            type(c_ptr), value :: real_coefficient, complex_coefficient
            integer(c_size_t), value :: stride, n
            integer(c_int) :: gsl_fft_real_unpack
        end function gsl_fft_real_unpack
        function gsl_fft_halfcomplex_unpack(halfcomplex_coefficient, complex_coefficient, &
                                            stride, n) bind(c)
            import :: c_size_t, c_ptr, c_int
            type(c_ptr), value :: halfcomplex_coefficient, complex_coefficient
            integer(c_size_t), value :: stride, n
            integer(c_int) :: gsl_fft_halfcomplex_unpack
        end function gsl_fft_halfcomplex_unpack
    end interface

end module gsl_fft_m
